#include <linux/module.h>
#include <linux/pci.h>
#include "drv_acm.h"
#include "drv_pcie.h"
#include "drv_cdev.h"
#include "drv_ai.h"
#include "drv_di.h"
#include "drv_pi.h"
#include "drv_do.h"
#include "drv_xcan.h"

#if (HARD_VER == 0)
#define ACM_AI_DEV_NUM          9                   /* AI 设备数量 */
#define ACM_DI_DEV_NUM          8                   /* DI 设备数量 */
#define ACM_PI_DEV_NUM          2                   /* PI 设备数量 */
#define ACM_DO_DEV_NUM          12                  /* DO 设备数量 */
#define ACM_CANFD_DEV_NUM       1                   /* CANFD 设备数量 */
#elif (HARD_VER == 1)
#define ACM_AI_DEV_NUM          9                   /* AI 设备数量 */
#define ACM_DI_DEV_NUM          8                   /* DI 设备数量 */
#define ACM_PI_DEV_NUM          2                   /* PI 设备数量 */
#define ACM_DO_DEV_NUM          12                  /* DO 设备数量 */
#define ACM_CANFD_DEV_NUM       2                   /* CANFD 设备数量 */
#endif
#define ACM_AI_DRV_NAME         "pcie_ai"           /* AI 设备名称 */
#define ACM_DI_DRV_NAME         "pcie_di"           /* DI 设备名称 */
#define ACM_PI_DRV_NAME         "pcie_pi"           /* PI 设备名称 */
#define ACM_DO_DRV_NAME         "pcie_do"           /* DO 设备名称 */
#define ACM_CANFD_DRV_NAME      "pcie_canfd"        /* CANFD 设备名称 */

struct cdev_dev_t acm_ai_cdev[ACM_AI_DEV_NUM];          /* AC 模块 AI 字符设备 */
struct ai_dev_t acm_ai_dev[ACM_AI_DEV_NUM];             /* AC 模块 AI 设备 */
struct cdev_dev_t acm_di_cdev[ACM_DI_DEV_NUM];          /* AC 模块 DI 字符设备 */
struct di_dev_t acm_di_dev[ACM_DI_DEV_NUM];             /* AC 模块 DI 设备 */
struct cdev_dev_t acm_pi_cdev[ACM_PI_DEV_NUM];          /* AC 模块 PI 字符设备 */
struct pi_dev_t acm_pi_dev[ACM_PI_DEV_NUM];             /* AC 模块 PI 设备 */
struct cdev_dev_t acm_do_cdev[ACM_DO_DEV_NUM];          /* AC 模块 DO 字符设备 */
struct do_dev_t acm_do_dev[ACM_DO_DEV_NUM];             /* AC 模块 DO 设备 */
struct cdev_dev_t acm_canfd_cdev[ACM_CANFD_DEV_NUM];    /* ECU 模块 CANFD 字符设备 */
struct xcan_dev_t acm_canfd_dev[ACM_CANFD_DEV_NUM];     /* ECU 模块 CANFD 设备 */

/* PCIe AC 模块 */
struct pcie_acm_t {
    struct device *dev;                 /* Linux 设备指针 */
    struct pcie_dev_t pcie_dev;         /* PCIe 设备 */
    struct ai_ctrl_t ai_ctrl;           /* AI 控制器 */
    struct di_ctrl_t di_ctrl;           /* DI 控制器 */
    struct pi_ctrl_t pi_ctrl;           /* PI 控制器 */
    struct do_ctrl_t do_ctrl;           /* DO 控制器 */
    struct xcan_ctrl_t xcanfd_ctrl;     /* CANFD 控制器 */
};

static int pcie_acm_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
    int ret = 0;
    struct pcie_acm_t *pmcdev = NULL;

    dev_info(&pdev->dev, "Probing %04x:%04x", pdev->vendor, pdev->device);
    /* 检查设备是否已被占用 */
    if (pci_get_drvdata(pdev)) {
        dev_warn(&pdev->dev, "device already claimed");
        return -EBUSY;
    }

    /* 分配设备结构内存 */
    pmcdev = devm_kzalloc(&pdev->dev, sizeof(*pmcdev), GFP_KERNEL);
    if (!pmcdev)
        return -ENOMEM;

    pmcdev->dev = &pdev->dev;
    pci_set_drvdata(pdev, pmcdev);

    /* 初始化 PCIe 设备 */
    ret = init_pcie_dev(pdev, &pmcdev->pcie_dev);
    if (ret) {
        dev_err(pmcdev->dev, "Init PCIe device failed");
        goto err_cleanup;
    }

    /* 初始化 AI 控制器 */
    ret = init_ai_ctrl(&pmcdev->pcie_dev, acm_ai_cdev, &pmcdev->ai_ctrl, 
                       acm_ai_dev, ACM_AI_DRV_NAME, ACM_AI_DEV_NUM, AI_TYPE_AC);
    if (ret < 0) {
        dev_err(pmcdev->dev, "Init AI controller failed");
        goto err_cleanup;
    }
    dev_info(pmcdev->dev, "Init AI controller success");

    /* 初始化 DI 控制器 */
    ret = init_di_ctrl(&pmcdev->pcie_dev, acm_di_cdev, &pmcdev->di_ctrl, 
                       acm_di_dev, ACM_DI_DRV_NAME, ACM_DI_DEV_NUM);
    if (ret < 0) {
        dev_err(pmcdev->dev, "Init DI controller failed");
        goto err_cleanup_ai_ctrl;
    }
    dev_info(pmcdev->dev, "Init DI controller success");

    /* 初始化 PI 控制器 */
    ret = init_pi_ctrl(&pmcdev->pcie_dev, acm_pi_cdev, &pmcdev->pi_ctrl, 
                       acm_pi_dev, ACM_PI_DRV_NAME, ACM_PI_DEV_NUM, PI_TYPE_AC);
    if (ret < 0) {
        dev_err(pmcdev->dev, "Init PI controller failed");
        goto err_cleanup_di_ctrl;
    }
    dev_info(pmcdev->dev, "Init PI controller success");

    /* 初始化 DO 控制器 */
    ret = init_do_ctrl(&pmcdev->pcie_dev, acm_do_cdev, &pmcdev->do_ctrl, 
                       acm_do_dev, ACM_DO_DRV_NAME, ACM_DO_DEV_NUM);
    if (ret < 0) {
        dev_err(pmcdev->dev, "Init DO controller failed");
        goto err_cleanup_pi_ctrl;
    }
    dev_info(pmcdev->dev, "Init DO controller success");

    /* 初始化 CAN FD 控制器 */
    ret = init_xcan_ctrl(&pmcdev->pcie_dev, acm_canfd_cdev, &pmcdev->xcanfd_ctrl, 
                         acm_canfd_dev, ACM_CANFD_DRV_NAME, ACM_CANFD_DEV_NUM, &xcan_canfd2_data);
    if (ret < 0) {
        dev_err(pmcdev->dev, "Init CANFD device failed");
        goto err_cleanup_do;
    }
    dev_info(pmcdev->dev, "Init CANFD device success");

    dev_info(&pdev->dev, "Probe PCIe %s device success", ACM_DRV_NAME);

    return 0;

err_cleanup_do:
    /* 注销 DO 控制器 */
    exit_do_ctrl(&pmcdev->do_ctrl, ACM_DO_DEV_NUM);
err_cleanup_pi_ctrl:
    /* 注销 PI 控制器 */
    exit_pi_ctrl(&pmcdev->pi_ctrl, ACM_PI_DEV_NUM);
err_cleanup_di_ctrl:
    /* 注销 DI 控制器 */
    exit_di_ctrl(&pmcdev->di_ctrl, ACM_DI_DEV_NUM);
err_cleanup_ai_ctrl:
#ifdef ACM_PT100
    /* 注销 PT100 控制器 */
    exit_pt_ctrl(&pmcdev->pt_ctrl, ACM_PT100_DEV_NUM);
#else
    /* 注销 AI 控制器 */
    exit_ai_ctrl(&pmcdev->ai_ctrl, ACM_AI_DEV_NUM);
#endif
err_cleanup:
    pci_set_drvdata(pdev, NULL);

    return ret;
}

static void pcie_acm_remove(struct pci_dev *pdev)
{
    struct pcie_acm_t *pmcdev = pci_get_drvdata(pdev);

    if (!pmcdev) {
        dev_warn(&pdev->dev, "No device data found");
        return;
    }
    dev_info(&pdev->dev, "Removing PCIe %s device", ACM_DRV_NAME);

    /* 清理 CAN FD 控制器 */
    exit_xcan_ctrl(&pmcdev->xcanfd_ctrl, ACM_CANFD_DEV_NUM);
    dev_info(pmcdev->dev, "Exit %s controller success", pmcdev->xcanfd_ctrl.name);

    /* 注销 DO 控制器 */
    exit_do_ctrl(&pmcdev->do_ctrl, ACM_DO_DEV_NUM);
    dev_info(pmcdev->dev, "Exit %s controller success", pmcdev->do_ctrl.name);

    /* 注销 PI 控制器 */
    exit_pi_ctrl(&pmcdev->pi_ctrl, ACM_PI_DEV_NUM);
    dev_info(pmcdev->dev, "Exit %s controller success", pmcdev->pi_ctrl.name);

    /* 注销 DI 控制器 */
    exit_di_ctrl(&pmcdev->di_ctrl, ACM_DI_DEV_NUM);
    dev_info(pmcdev->dev, "Exit %s controller success", pmcdev->di_ctrl.name);

    /* 注销 AI 控制器 */
    exit_ai_ctrl(&pmcdev->ai_ctrl, ACM_AI_DEV_NUM);
    dev_info(pmcdev->dev, "Exit %s controller success", pmcdev->ai_ctrl.name);

    /* 注销 PCIe 设备 */
    exit_pcie_dev(pdev, &pmcdev->pcie_dev);
    dev_info(&pdev->dev, "Exit %s device success", pmcdev->pcie_dev.name);

    pci_set_drvdata(pdev, NULL);
    dev_info(&pdev->dev, "Remove PCIe %s device success", ACM_DRV_NAME);
}

/* PCI 设备 ID 表 */
static const struct pci_device_id pcie_acm_ids[] = {
    { PCI_DEVICE(0x594D, 0x0008) },     /* ac module */
    { 0, }
};
MODULE_DEVICE_TABLE(pci, pcie_acm_ids);

/* PCI AC 驱动结构 */
struct pci_driver pcie_acm_driver = {
    .name = ACM_DRV_NAME,
    .id_table = pcie_acm_ids,
    .probe = pcie_acm_probe,
    .remove = pcie_acm_remove,
};
